package com.study.crypto;


import org.apache.commons.codec.digest.DigestUtils;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

public class CryptoTest {

    public static void main(String[] args) throws NoSuchAlgorithmException {
        jdkMD5("123");
        bcMD5("123");

        jdkSHA1("123");
        bcSHA1("123");
        ccSHA1("123");

        jdkDES("123");
        bcDES("123");

        rsaKey();
    }

    public static void jdkMD5(String src) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            System.out.println("JDK MD5: " + Hex.toHexString(md.digest(src.getBytes())));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    public static void bcMD5(String src) {
        //方式一
        Digest digest = new MD5Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] md5Bytes = new byte[digest.getDigestSize()];
        digest.doFinal(md5Bytes, 0);
        System.out.println("BC MD5: " + Hex.toHexString(md5Bytes));


//        //方式二(通过添加provider的方式，将sun的改为bc的provider)
//        try {
//            Security.addProvider(new BouncyCastleProvider());  //通过添加provider的方式
//            MessageDigest md = MessageDigest.getInstance("MD5");
//            System.out.println("BC MD5: " + Hex.toHexString(md.digest(src.getBytes())));
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        }
    }

    public static void jdkSHA1(String src) {
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("SHA-1");
            digest.update(src.getBytes());
            System.out.println("JDK SHA-1: " + Hex.toHexString(digest.digest()));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    public static void bcSHA1(String src) {
        Digest digest = new SHA1Digest();
        digest.update(src.getBytes(), 0, src.getBytes().length);
        byte[] sha1Byte1 = new byte[digest.getDigestSize()];
        digest.doFinal(sha1Byte1, 0);
        System.out.println("BC SHA-1:" + org.bouncycastle.util.encoders.Hex.toHexString(sha1Byte1));
    }

    public static void ccSHA1(String src) {
        System.out.println("CC SHA-1:" + DigestUtils.sha1Hex(src));
    }

    public static void jdkDES(String src) {
        try {
            //生成key
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
            keyGenerator.init(56);      //指定key长度，同时也是密钥长度(56位)
            SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
            byte[] key = secretKey.getEncoded();  //生成key
            System.out.println("密钥：" + Hex.toHexString(key));

            //key转换成密钥
            DESKeySpec desKeySpec = new DESKeySpec(key);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            SecretKey key2 = factory.generateSecret(desKeySpec);      //转换后的密钥

            //加密
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");  //算法类型/工作方式/填充方式
            cipher.init(Cipher.ENCRYPT_MODE, key2);   //指定为加密模式
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("jdkDES加密: " + Hex.toHexString(result));  //转换为十六进制

            //解密
            cipher.init(Cipher.DECRYPT_MODE, key2);  //相同密钥，指定为解密模式
            result = cipher.doFinal(result);   //根据加密内容解密
            System.out.println("jdkDES解密: " + new String(result));  //转换字符串

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void bcDES(String src) {
        try {
            //通过改变provider的方式
            Security.addProvider(new BouncyCastleProvider());

            //生成key,使用bc需要在后面指定"BC"
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DES", "BC");

            keyGenerator.getProvider();

            keyGenerator.init(64);      //指定key长度，同时也是密钥长度
            SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
            byte[] key = secretKey.getEncoded();  //生成key
            System.out.println("密钥：" + Hex.toHexString(key));

            //key转换成密钥
            DESKeySpec desKeySpec = new DESKeySpec(key);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            SecretKey key2 = factory.generateSecret(desKeySpec);      //转换后的密钥

            //加密
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");  //算法类型/工作方式/填充方式
            cipher.init(Cipher.ENCRYPT_MODE, key2);
            byte[] result = cipher.doFinal(src.getBytes());
            System.out.println("bcDES加密: " + Hex.toHexString(result));  //转换为十六进制

            //解密
            cipher.init(Cipher.DECRYPT_MODE, key2);  //相同密钥
            result = cipher.doFinal(result);   //根据加密内容解密
            System.out.println("bcDES解密: " + new String(result));  //转换字符串

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void rsaKey() throws NoSuchAlgorithmException {
        //实例化密钥生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        //初始化密钥生成器
        keyPairGenerator.initialize(512);
        //生成密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        //甲方公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        System.out.println("系数：" + publicKey.getModulus() + "  加密指数：" + publicKey.getPublicExponent());
        //甲方私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        System.out.println("系数：" + privateKey.getModulus() + "解密指数：" + privateKey.getPrivateExponent());
    }
}
